import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'
import { DetailBaseClass } from '@shared/classes/DetailBaseClass'
import { ITrade, ECategoryUrl, ITradeRefund, ERefundType, ManualTrans } from '@shared/interfaces/trade'
import { I18NService } from '@core'
import { Router, ActivatedRoute } from '@angular/router'
import { SettingsService } from '@delon/theme'
import { TradeService } from '../trade-abstract.service'
import { PageService } from '@shared/services/page.service'
import { IBaseInfoColumn } from '@shared/interfaces/baseInfo'
import { DataService } from '@shared/services/data.service'
import { FormGroup, FormBuilder, Validators } from '@angular/forms'
import {
  refundAmtRegSupportDecimal,
  refundAmtRegNotSupportDecimal,
  merchantauthPasswordReg,
} from 'app/utils/contraints'
import { Observable, of, BehaviorSubject } from 'rxjs'
import { CurrencyService } from '@shared/services/currency.service'
import { makeAllControlDirty } from 'app/utils/helpers'
import { mergeMap } from 'rxjs/operators'
import { NzMessageService } from 'ng-zorro-antd'
import { AmtFormatPipe } from '@shared/filters/amt-format.pipe'

@Component({
  selector: 'app-trades-batch-present',
  templateUrl: './present.component.html',
  styleUrls: ['./present.component.less'],
})
export class TradesBatchPresentComponent extends DetailBaseClass<ITrade> implements OnInit {
  detailData: ITrade
  firstColumns: IBaseInfoColumn[]
  acquirerColumns: IBaseInfoColumn[]
  storeColumns: IBaseInfoColumn[]
  validateForm: FormGroup
  allTxamt: number
  ERefundType = ERefundType

  /** 是否支持小数点 */
  isSupportDecimal: boolean

  loading = true

  /** 可退款金额 */
  availableRefundAmt: number

  /** 错误处理 */
  errorTips = {}

  refundType: ERefundType
  @ViewChild('tpCurrency') tpCurrency: TemplateRef<any>
  constructor(
    public fb: FormBuilder,
    public i18n: I18NService,
    public router: Router,
    public route: ActivatedRoute,
    public tradeService: TradeService,
    public pageService: PageService,
    private dataService: DataService,
    private currencyService: CurrencyService,
    private settingService: SettingsService,
    private msg: NzMessageService,
    private amtFormatPipe: AmtFormatPipe,
  ) {
    super(pageService)
  }

  ngOnInit() {
    this.checkManualTransList()
    this.initErrorTips()
    this.refundType = this.route.snapshot.data.refundType
    this.getTradeData().subscribe(trade => {
      this.detailData = trade
      const isSupport$ = this.checkIsSupportDecimal()
      isSupport$.subscribe(isSupportDecimal => {
        this.isSupportDecimal = isSupportDecimal
        this.availableRefundAmt = this.calAvailableRefundAmt()
        this.initForm()
        this.loading = false
      })
    })
  }

  initErrorTips(): void {
    this.errorTips = {
      txamt: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('TRADE.REFUND.AMT') }),
        max: this.trans('TRADE.REFUND.VALIDATION.MAX_AMT'),
        pattern: this.trans('VALIDATION.PATTERN.VALID_AMT'),
      },
      refundDetail: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('TRADE.REFUND.REMARK') }),
        maxlength: this.trans('VALIDATION.MAX_LENGTH', { length: 128 }),
      },
      authPassword: {
        required: this.trans('VALIDATION.REQUIRED', { name: this.trans('BIZ.MERCHANT.OTHER.TRADE.AUTH_CODE') }),
        minlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 6 }),
        maxlength: this.trans('VALIDATION.FIXED_LENGTH', { length: 6 }),
        pattern: this.trans('VALIDATION.PATTERN.NUMBER_ONLY'),
      },
    }
  }

  checkIsSupportDecimal(): Observable<boolean> {
    const { currency: code } = this.detailData
    return this.currencyService
      .getAllCurrency()
      .pipe(mergeMap(currencies => of(currencies.find(c => c.code === code).decimal === 2)))
  }

  // 如果批请列表为空，则让用户回到批请页面重新勾选
  checkManualTransList(): void {
    const manualTransList = this.dataService.batchPresentList
    if (manualTransList.length === 0) {
      this.router.navigate(['../'], { relativeTo: this.route })
    }
  }

  getTradeData(): Observable<ITrade> {
    if (this.dataService.trade.orderNum) {
      return new BehaviorSubject(this.dataService.trade)
    }
    const orderNum = this.route.snapshot.params['orderNum']
    const intStoreCode = this.route.snapshot.params['intStoreCode']
    const category = this.route.snapshot.params['category'] as string
    return this.tradeService.getOne({ orderNum, intStoreCode }, ECategoryUrl[category])
  }

  initForm(): void {
    this.initFirstColumns()
    this.initAcquirerColumns()
    this.initStoreColumns()
    this.initColumns()
    this.setupForm()
  }

  initColumns(): void {
    this.initValue.call(this, this.firstColumns)
    this.initValue.call(this, this.acquirerColumns)
    this.initValue.call(this, this.storeColumns)
  }

  initFirstColumns(): void {
    const { transAmt, currency } = this.detailData
    this.firstColumns = [
      {
        span: 8,
        index: 'terminalid',
        label: 'GENERAL.TERMINAL.CODE',
        labelI18n: 'GENERAL.TERMINAL.CODE',
      },
      {
        span: 8,
        index: 'batchNum',
        label: 'TRADE.BATCHNUM',
        labelI18n: 'TRADE.BATCHNUM',
      },
      {
        span: 8,
        index: 'currency',
        label: 'GENERAL.INFO.TRANSACTION_CURRENCY',
        labelI18n: 'GENERAL.INFO.TRANSACTION_CURRENCY',
        template: this.tpCurrency,
      },
    ]
  }

  initAcquirerColumns(): void {
    this.acquirerColumns = [
      {
        span: 8,
        index: 'insCode',
        label: 'GENERAL.INSTITUTION.CODE',
        labelI18n: 'GENERAL.INSTITUTION.CODE',
      },
      {
        span: 8,
        index: 'insName',
        label: 'GENERAL.INSTITUTION.NAME',
        labelI18n: 'GENERAL.INSTITUTION.NAME',
      },
      {
        span: 8,
        index: 'insNameEN',
        label: 'GENERAL.INSTITUTION.NAME_EN',
        labelI18n: 'GENERAL.INSTITUTION.NAME_EN',
      },
    ]
  }

  initStoreColumns(): void {
    this.storeColumns = [
      {
        span: 8,
        index: 'storeNum',
        label: 'GENERAL.STORE.NUM',
        labelI18n: 'GENERAL.STORE.NUM',
      },
      {
        span: 8,
        index: 'storeName',
        label: 'GENERAL.STORE.NAME',
        labelI18n: 'GENERAL.STORE.NAME',
      },
      {
        span: 8,
        index: 'storeNameEN',
        label: 'GENERAL.STORE.NAME_EN',
        labelI18n: 'GENERAL.STORE.NAME_EN',
      },
    ]
  }

  setupForm(): void {
    const manualTransList = this.dataService.batchPresentList
    this.allTxamt = 0
    const { currency } = this.detailData
    manualTransList.forEach(item => {
      this.allTxamt += item.transAmt
    })
    this.amtFormatPipe.parsePrice(this.allTxamt.toString(), currency, '', false).subscribe(
      value => {
        this.validateForm = this.fb.group({
          txamt: [value, [Validators.required]],
          num: [manualTransList.length, []],
          refundDetail: [null, [Validators.required, Validators.maxLength(128)]],
        })
      }
    )
  }

  submitRefund(): void {
    const valid = this.checkValid()
    if (valid) {
      this.persent()
    } else {
      makeAllControlDirty(this.validateForm)
    }
  }

  private persent(): void {
    // 手工请款 TODO
    const reqData = this.getManualPresentData()
    this.tradeService.manualPresent({ manualTransList: reqData }).subscribe(
      isSuccess => {
        setTimeout(() => {
          this.msg.success(this.trans('GENERAL.NOTIFICATION.OPERATION_SUCCESS'))
        })
        this.router.navigate(['../../../../'], { relativeTo: this.route })
      },
      err => {
        this.msg.error(this.trans('GENERAL.NOTIFICATION.OPERATION_FAIL'))
      },
    )
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private checkValid() {
    return this.validateForm.valid
  }

  private getManualPresentData(): ManualTrans[] {
    const { username } = this.settingService.user
    const manualTransList = this.dataService.batchPresentList
    const { refundDetail } = this.validateForm.value
    manualTransList.forEach(item => {
      item.remark = refundDetail
      item.operator = username
    })
    return manualTransList
  }

  private calAvailableRefundAmt(): number {
    return this.detailData.transAmt - (this.detailData.refundAmt || 0) - (this.detailData.discountAmt || 0)
  }
}
